#ifndef DATASEGMENTMANAGER_H_
#define DATASEGMENTMANAGER_H_

#include <string>
#include <map>
#include <set>
#include "status.hxx"
#include "dbt.hxx"

class DataSegment;
class DataStoreImpl;
class DataSegment;
class DbPartition;

/**
 * DataSegmentManager manage a bunch of datasegments, including
 * creating/deleting detasegment, access to datasegment 
 */
class DataSegmentManager {

private:
    //only nextSegment() update the map
    pthread_rwlock_t m_rwlockMap;
    std::map<uint16_t, DataSegment*> *m_segments;
	std::string m_partitionPath;
	DataStoreImpl* m_ds;
    DbPartition* m_partition;

    //for put/del
	DataSegment* m_activeSeg;

    //for compaction
    DataSegment* m_activeSegCompact;

public:
	DataSegmentManager(DataStoreImpl& ds, DbPartition& partition);
    ~DataSegmentManager();

	//load all of segments
	DbStatus init();

    //flush the data of all datasegment
	DbStatus flush();

	DbStatus get(uint16_t segID, uint32_t offset, uint32_t& dataSize, std::string& result);
    DbStatus get(uint16_t segID, uint32_t offset, uint32_t& dataSize, Dbt& dbt);

	DbStatus put(std::string& data, uint16_t& segID, uint32_t& offset, uint32_t& loadSize);
    DbStatus put(Dbt& dbt, uint16_t& segID, uint32_t& offset, uint32_t& loadSize);

	DataSegment* getSegment(uint16_t segID);
	DbStatus nextSegment(DataSegment*& seg);

    //return a list of segment ID, each of which has (actual data size/segment
    //capacity) < validDataRatio
    std::set<uint16_t> getSegmentIDsForCompact(double validDataRatio);
    std::set<uint16_t> getSegmentIDsNotAlive();
    
    //release the segment
    DbStatus discardSegment(uint16_t segID);
	
private:	
	DbStatus loadSegments();
    uint16_t nextSegID();

};

#endif
